<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html>
<head>
<title>GTK+ layout management</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="GUI, GTK+ layout management, GTK+ library, C">
<meta name="description" content="GTK+ layout management">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content">


<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>GTK+ layout management</h1>


<p>
In this chapter we will show how to lay out our widgets in windows or dialogs. 
</p>

<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div>

<p>
When we design the GUI of our application, we decide what widgets we will 
use and how we will organize those widgets in the application. To organize 
our widgets, we use specialized non visible widgets called <b>layout containers</b>. 
In this chapter, we will mention <b class="keyword">GtkAlignment</b>,
<b class="keyword">GtkFixed</b>, <b class="keyword">GtkVBox</b> and 
<b class="keyword">GtkTable</b>.
</p>


<h2>GtkFixed</h2>

<p>
The <b class="keyword">GtkFixed</b> container places child widgets at fixed 
positions and with fixed sizes. This container performs no automatic layout 
management. In most applications, we don't use GtkFixed container. There 
are some specialized areas, where we use this container. For example games, 
specialized applications that work with diagrams, resizable components that 
can be moved (like a chart in a spreadsheet application), small educational examples. 
</p>

<pre class="code">
#include &lt;gtk/gtk.h&gt;


int main( int argc, char *argv[])
{
  GtkWidget *window;
  GtkWidget *fixed;

  GtkWidget *button1;
  GtkWidget *button2;
  GtkWidget *button3;

  gtk_init(&amp;argc, &amp;argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(window), "GtkFixed");
  gtk_window_set_default_size(GTK_WINDOW(window), 290, 200);
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

  fixed = gtk_fixed_new();
  gtk_container_add(GTK_CONTAINER(window), fixed);

  button1 = gtk_button_new_with_label("Button");
  gtk_fixed_put(GTK_FIXED(fixed), button1, 150, 50);
  gtk_widget_set_size_request(button1, 80, 35);

  button2 = gtk_button_new_with_label("Button");
  gtk_fixed_put(GTK_FIXED(fixed), button2, 15, 15);
  gtk_widget_set_size_request(button2, 80, 35);

  button3 = gtk_button_new_with_label("Button");
  gtk_fixed_put(GTK_FIXED(fixed), button3, 100, 100);
  gtk_widget_set_size_request(button3, 80, 35);

  g_signal_connect_swapped(G_OBJECT(window), "destroy", 
      G_CALLBACK(gtk_main_quit), NULL);

  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}
</pre>

<p>
In our example, we create three buttons and place them at fixed coordinates. 
When we resize the window of the application, the buttons keep their size and positions.
</p>

<pre class="explanation">
 fixed = gtk_fixed_new();
</pre>

<p>
Here a <b class="keyword">GtkFixed</b> container widget is created. 
</p>

<pre class="explanation">
 gtk_fixed_put(GTK_FIXED(fixed), button1, 150, 50);
</pre>

<p>
The first button is placed using the <b class="keyword">gtk_fixed_put()</b> 
function at coordinates x=150, y=50.
</p>


<br>
<img src="/img/gui/cgtk/fixed.png" alt="GtkFixed container">
<div class="figure">Figure: GtkFixed container</div>
<br>


<h2>GtkVBox</h2>

<p>
<b class="keyword">GtkVBox</b> is a vertical box container. It places its 
child widgets into a single column. 
<b class="keyword">GtkHBox</b> is a very similar container This container 
places its child widgets into a single row. 
</p>

<pre class="code">
#include &lt;gtk/gtk.h&gt;


int main( int argc, char *argv[])
{

  GtkWidget *window;
  GtkWidget *vbox;

  GtkWidget *settings;
  GtkWidget *accounts;
  GtkWidget *loans;
  GtkWidget *cash;
  GtkWidget *debts;

  gtk_init(&amp;argc, &amp;argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(window), 230, 250);
  gtk_window_set_title(GTK_WINDOW(window), "GtkVBox");
  gtk_container_set_border_width(GTK_CONTAINER(window), 5);

  vbox = gtk_vbox_new(TRUE, 1);
  gtk_container_add(GTK_CONTAINER(window), vbox);

  settings = gtk_button_new_with_label("Settings");
  accounts = gtk_button_new_with_label("Accounts");
  loans = gtk_button_new_with_label("Loans");
  cash = gtk_button_new_with_label("Cash");
  debts = gtk_button_new_with_label("Debts");

  gtk_box_pack_start(GTK_BOX(vbox), settings, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), accounts, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), loans, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), cash, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), debts, TRUE, TRUE, 0);

  g_signal_connect_swapped(G_OBJECT(window), "destroy",
        G_CALLBACK(gtk_main_quit), G_OBJECT(window));

  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}
</pre>

<p>
This example shows a <b class="keyword">GtkVBox</b> in action. 
It packs five buttons into one column. If we resize the window of 
the application, the child widgets are resized as well.  
</p>

<pre class="explanation">
 vbox = gtk_vbox_new(TRUE, 1);
</pre>

<p>
The <b class="keyword">GtkVBox</b> is created. We set the homogeneous
parameter to TRUE. This means that all our buttons will be of the 
same size. The spacing between widgets is set to 1 pixel. 
</p>

<pre class="explanation">
 gtk_box_pack_start(GTK_BOX(vbox), settings, TRUE, TRUE, 0);
</pre>

<p>
We pack a settings button into the container. The first two parameters are 
the container and the child widget. The next three parameters are expand, 
fill and padding. Note that the fill parameter has no effect, if the 
expand paramater is set to FALSE. Similarly, the expand parameter has no 
effect if we have created the container with homegeneous parameter set to TRUE.
</p>


<br>
<img src="/img/gui/cgtk/gtkvbox.png" alt="GtkVBox container">
<div class="figure">Figure: GtkVBox container</div>
<br>



<h2>GtkTable</h2>

<p>
The <b class="keyword">GtkTable</b> widget arranges widgets in rows and columns.
</p>

<pre class="code">
#include &lt;gtk/gtk.h&gt;


int main( int argc, char *argv[])
{

  GtkWidget *window;

  GtkWidget *table;
  GtkWidget *button;

  char *values[16] = { "7", "8", "9", "/", 
     "4", "5", "6", "*",
     "1", "2", "3", "-",
     "0", ".", "=", "+"
  };

  gtk_init(&amp;argc, &amp;argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(window), 250, 180);
  gtk_window_set_title(GTK_WINDOW(window), "GtkTable");

  gtk_container_set_border_width(GTK_CONTAINER(window), 5);

  table = gtk_table_new(4, 4, TRUE);
  gtk_table_set_row_spacings(GTK_TABLE(table), 2);
  gtk_table_set_col_spacings(GTK_TABLE(table), 2);

  int i = 0;
  int j = 0;
  int pos = 0;

  for( i=0; i < 4; i++) {
    for( j=0; j < 4; j++) {
      button = gtk_button_new_with_label(values[pos]);
      gtk_table_attach_defaults(GTK_TABLE(table), button, j, j+1, i, i+1 );
      pos++;
    }
  }

  gtk_container_add(GTK_CONTAINER(window), table);

  g_signal_connect_swapped(G_OBJECT(window), "destroy",
        G_CALLBACK(gtk_main_quit), G_OBJECT(window));

  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}
</pre>

<p>
In this example, we will create a set of buttons, that we see in calculators. 
</p>

<pre class="explanation">
 table = gtk_table_new(4, 4, TRUE);
</pre>

<p>
 We create a new <b class="keyword">GtkTable</b> widget with 4 rows and 4 columns. 
</p>

<pre class="explanation">
 gtk_table_set_row_spacings(GTK_TABLE(table), 2);
 gtk_table_set_col_spacings(GTK_TABLE(table), 2);
</pre>

<p>
We set some space between every row and every column. 
</p>

<pre class="explanation">
 for( i=0; i < 4; i++) {
   for( j=0; j < 4; j++) {
     button = gtk_button_new_with_label(values[pos]);
     gtk_table_attach_defaults(GTK_TABLE(table), button, j, j+1, i, i+1 );
     pos++;
   }
 }
</pre>

<p>
This code will create 16 buttons and place them into the container. 
</p>


<br>
<img src="/img/gui/cgtk/gtktable.png" alt="GtkTable container">
<div class="figure">Figure: GtkTable container</div>
<br>

<h2>GtkAlignment</h2>

<p>
The <b class="keyword">GtkAlignment</b> container controls the alignment and 
the size of its child widget. 
</p>

<pre class="code">
#include &lt;gtk/gtk.h&gt;


int main( int argc, char *argv[])
{

  GtkWidget *window;
  GtkWidget *ok;
  GtkWidget *close;

  GtkWidget *vbox;
  GtkWidget *hbox;
  GtkWidget *halign;
  GtkWidget *valign;

  gtk_init(&amp;argc, &amp;argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(window), 350, 200);
  gtk_window_set_title(GTK_WINDOW(window), "GtkAlignment");
  gtk_container_set_border_width(GTK_CONTAINER(window), 10);

  vbox = gtk_vbox_new(FALSE, 5);

  valign = gtk_alignment_new(0, 1, 0, 0);
  gtk_container_add(GTK_CONTAINER(vbox), valign);
  gtk_container_add(GTK_CONTAINER(window), vbox);

  hbox = gtk_hbox_new(TRUE, 3);

  ok = gtk_button_new_with_label("OK");
  gtk_widget_set_size_request(ok, 70, 30);
  gtk_container_add(GTK_CONTAINER(hbox), ok);
  close = gtk_button_new_with_label("Close");
  gtk_container_add(GTK_CONTAINER(hbox), close);

  halign = gtk_alignment_new(1, 0, 0, 0);
  gtk_container_add(GTK_CONTAINER(halign), hbox);

  gtk_box_pack_start(GTK_BOX(vbox), halign, FALSE, FALSE, 0);

  g_signal_connect_swapped(G_OBJECT(window), "destroy",
        G_CALLBACK(gtk_main_quit), G_OBJECT(window));

  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}
</pre>

<p>
In the code example, we place two buttons into the right bottom 
corner of the window. To accomplish this, we use one horizontal 
box and one vertical box and two alignment containers. 
</p>

<pre class="explanation">
 valign = gtk_alignment_new(0, 1, 0, 0);
</pre>

<p>
This will put the child widget to the bottom. 
</p>

<pre class="explanation">
 gtk_container_add(GTK_CONTAINER(vbox), valign);
</pre>

<p>
Here we place the alignment widget into the vertical box. 
</p>

<pre class="explanation">
 hbox = gtk_hbox_new(TRUE, 3);

 ok = gtk_button_new_with_label("OK");
 gtk_widget_set_size_request(ok, 70, 30);
 gtk_container_add(GTK_CONTAINER(hbox), ok);
 close = gtk_button_new_with_label("Close");
 gtk_container_add(GTK_CONTAINER(hbox), close);
</pre>

<p>
We create a horizontal box and put two buttons inside it.
</p>

<pre class="explanation">
 halign = gtk_alignment_new(1, 0, 0, 0);
 gtk_container_add(GTK_CONTAINER(halign), hbox);

 gtk_box_pack_start(GTK_BOX(vbox), halign, FALSE, FALSE, 0);
</pre>

<p>
This will create an alignment container that will place its child 
widget the right. We add the horizontal box into the alignment container 
and pack the alignment container into the vertical box. We must keep 
in mind that the alignment container takes only one child widget. 
That's why we must use boxes. 
</p>


<br>
<img src="/img/gui/cgtk/gtkalignment.png" alt="GtkAlignment container">
<div class="figure">Figure: GtkAlignment container</div>
<br>


<h2>Windows</h2>


<p>
Next we will create a more advanced example. We show a window, 
that can be found in the JDeveloper IDE. 
</p>

<br>
<img src="/img/gui/cgtk/jdevwindows.png" alt="Windows dialog in JDeveloper">
<div class="figure">Figure: Windows dialog in JDeveloper</div>
<br>

<p>
The dialog shows all opened windows, or more precisely tabs in 
JDeveloper application.
</p>

<pre class="code">
#include &lt;gtk/gtk.h&gt;


int main( int argc, char *argv[])
{

  GtkWidget *window;
  GtkWidget *table;

  GtkWidget *title;
  GtkWidget *activate;
  GtkWidget *halign;
  GtkWidget *halign2;

  GtkWidget *valign;
  GtkWidget *close;
  GtkWidget *wins;

  GtkWidget *help;
  GtkWidget *ok;

  gtk_init(&amp;argc, &amp;argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_widget_set_size_request (window, 300, 250);
  gtk_window_set_resizable(GTK_WINDOW(window), FALSE);

  gtk_window_set_title(GTK_WINDOW(window), "Windows");

  gtk_container_set_border_width(GTK_CONTAINER(window), 15);

  table = gtk_table_new(8, 4, FALSE);
  gtk_table_set_col_spacings(GTK_TABLE(table), 3);

  title = gtk_label_new("Windows");
  halign = gtk_alignment_new(0, 0, 0, 0);
  gtk_container_add(GTK_CONTAINER(halign), title);
  gtk_table_attach(GTK_TABLE(table), halign, 0, 1, 0, 1, 
      GTK_FILL, GTK_FILL, 0, 0);

  wins = gtk_text_view_new();
  gtk_text_view_set_editable(GTK_TEXT_VIEW(wins), FALSE);
  gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(wins), FALSE);
  gtk_table_attach(GTK_TABLE(table), wins, 0, 2, 1, 3,
      GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 1, 1);

  activate = gtk_button_new_with_label("Activate");
  gtk_widget_set_size_request(activate, 50, 30);
  gtk_table_attach(GTK_TABLE(table), activate, 3, 4, 1, 2, 
      GTK_FILL, GTK_SHRINK, 1, 1);

  valign = gtk_alignment_new(0, 0, 0, 0);
  close = gtk_button_new_with_label("Close");
 
  gtk_widget_set_size_request(close, 70, 30);
  gtk_container_add(GTK_CONTAINER(valign), close);
  gtk_table_set_row_spacing(GTK_TABLE(table), 1, 3);
  gtk_table_attach(GTK_TABLE(table), valign, 3, 4, 2, 3, 
      GTK_FILL, GTK_FILL | GTK_EXPAND, 1, 1);

  halign2 = gtk_alignment_new(0, 1, 0, 0);
  help = gtk_button_new_with_label("Help");
  gtk_container_add(GTK_CONTAINER(halign2), help);
  gtk_widget_set_size_request(help, 70, 30);
  gtk_table_set_row_spacing(GTK_TABLE(table), 3, 6);
  gtk_table_attach(GTK_TABLE(table), halign2, 0, 1, 4, 5, 
      GTK_FILL, GTK_FILL, 0, 0);

  ok = gtk_button_new_with_label("OK");
  gtk_widget_set_size_request(ok, 70, 30);
  gtk_table_attach(GTK_TABLE(table), ok, 3, 4, 4, 5, 
      GTK_FILL, GTK_FILL, 0, 0);

  gtk_container_add(GTK_CONTAINER(window), table);

  g_signal_connect_swapped(G_OBJECT(window), "destroy",
        G_CALLBACK(gtk_main_quit), G_OBJECT(window));

  gtk_widget_show_all(window);
  gtk_main();

  return 0;
}
</pre>

<p>
This code shows, how we could create a similar window in GTK+.
</p>

<pre class="explanation">
 table = gtk_table_new(8, 4, FALSE);
</pre>

<p>
We use a table container widget.
</p>

<pre class="explanation">
 title = gtk_label_new("Windows");
 halign = gtk_alignment_new(0, 0, 0, 0);
 gtk_container_add(GTK_CONTAINER(halign), title);
 gtk_table_attach(GTK_TABLE(table), halign, 0, 1, 0, 1, 
     GTK_FILL, GTK_FILL, 0, 0);
</pre>

<p>
This code creates a label, that is aligned to the left. The label is placed 
in the first row of the <b class="keyword">GtkTable</b> container. 
</p>

<pre class="explanation">
 wins = gtk_text_view_new();
 gtk_text_view_set_editable(GTK_TEXT_VIEW(wins), FALSE);
 gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(wins), FALSE);
 gtk_table_attach(GTK_TABLE(table), wins, 0, 2, 1, 3, 
     GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 1, 1);
</pre>

<p>
The text view widget spans two rows and two columns. We make the widget 
non editable and hide the cursor. 
</p>

<pre class="explanation">
 valign = gtk_alignment_new(0, 0, 0, 0);
 close = gtk_button_new_with_label("Close");
 
 gtk_widget_set_size_request(close, 70, 30);
 gtk_container_add(GTK_CONTAINER(valign), close);
 gtk_table_set_row_spacing(GTK_TABLE(table), 1, 3);
 gtk_table_attach(GTK_TABLE(table), valign, 3, 4, 2, 3, 
     GTK_FILL, GTK_FILL | GTK_EXPAND, 1, 1);
</pre>

<p>
We put the close button next to the text view widget into the fourth 
column. (we count from zero) We add the button into the alignment widget, 
so that we can align it to the top. 
</p>

<br>
<img src="/img/gui/cgtk/windows.png" alt="Windows">
<div class="figure">Figure: Windows</div>
<br>

<hr class="btm">

<p>
This chapter was dedicated to layout management.
</p>


<br>
<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div>
<br>


<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified March 26, 2008  <span class="copyright">&copy; 2007 - 2012 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>
